package com.vip.jwt.controller;

import cn.hutool.core.codec.Base64;
import com.vip.jwt.common.utils.ConvertUtil;
import com.vip.jwt.common.utils.app.APPWXPayUtil;
import com.vip.jwt.common.utils.sign.WXSignUtil;
import com.vip.jwt.common.utils.sign.ZFBSignUtil;
import com.vip.jwt.common.utils.xcx.wx.WXPayUtil;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @author vip
 * @date 2020-11-7 21:35
 */
@RestController
@RequestMapping("/api/callback")
public class CallbackController {


    @Getter
    private static String SDK_APP_ID;

    @Value("${tencent-trtc-sdkappid}")
    public void setSdkAppId(String sdkAppId) {
        SDK_APP_ID = sdkAppId;
    }

    /**
     * 微信支付回调
     * @param request
     * @param response
     * @throws Exception
     */
    @PostMapping("/wx")
    public void wxCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml>";
        BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)request.getInputStream()));
        String line;
        StringBuilder sb = new StringBuilder();
        while((line = br.readLine()) != null){
            sb.append(line);
        }
        br.close();
        // sb为微信返回的xml
        String notifyXml = sb.toString();
        // 验证支付信息并更新支付信息
        Map<String,String> map = ConvertUtil.xmlToMap(notifyXml);
        assert map != null;
        String returnCode = map.get("return_code");
        String resultCode = map.get("result_code");
        if("SUCCESS".equals(returnCode) && "SUCCESS".equals(resultCode)){
            boolean signatureValid = WXSignUtil.isSignatureValid(map, WXPayUtil.getAPI_SECRET());
            if(signatureValid){
                // 微信支付订单号
                String transactionId = map.get("transaction_id");
                // 订单金额（分）
                int totalFee = Integer.parseInt(map.get("total_fee"));
                // 商户订单号
                String outTradeNo = map.get("out_trade_no");
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml>";
            }
        }
        BufferedOutputStream out = new BufferedOutputStream(
                response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();
    }

    /**
     * 微信退款回调
     * @param request
     * @param response
     * @throws Exception
     */
    @PostMapping("/wx/refund")
    public void wxRefundCallback(HttpServletRequest request,HttpServletResponse response) throws Exception{
        String resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml>";
        BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)request.getInputStream()));
        String line;
        StringBuilder sb = new StringBuilder();
        while((line = br.readLine()) != null){
            sb.append(line);
        }
        br.close();
        // sb为微信返回的xml
        String notifyXml = sb.toString();
        // 验证支付信息并更新支付信息
        Map<String,String> map = ConvertUtil.xmlToMap(notifyXml);
        assert map != null;
        String returnCode = map.get("return_code");
        if("SUCCESS".equals(returnCode)){
            String reqInfo = map.get("req_info");
            byte[] base64ByteArr = Base64Utils.decodeFromString(reqInfo);
            // 商户Key，获取方式：微信商户平台(pay.weixin.qq.com)-->账户中心-->账户设置-->API安全-->设置密钥
            String apiSecret = APPWXPayUtil.getAPI_SECRET();
            String mchIdMD5Str = WXSignUtil.MD5(apiSecret).toLowerCase();
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            SecretKeySpec secretKeySpec = new SecretKeySpec(mchIdMD5Str.getBytes(), "AES");
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
            String xmlStr = new String(cipher.doFinal(base64ByteArr), StandardCharsets.UTF_8);
            Map<String, String> reqInfoMap = ConvertUtil.xmlToMap(xmlStr);
            if(reqInfoMap!=null){
                String outTradeNo = reqInfoMap.get("out_trade_no");
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml>";
            }
        }
        BufferedOutputStream out = new BufferedOutputStream(
                response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();
    }

    /**
     * 支付宝支付回调
     * @param request
     * @param response
     * @throws Exception
     */
    @PostMapping("/zfb")
    public void zfCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String res = "fail";
        // 构造传入参数
        Map<String,String> map = new HashMap<>();
        Map<String,String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
//            try {
//                valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
//            } catch (UnsupportedEncodingException e) {
//                logger.info("parse alipay callback data encoding error", e);
//                throw new MyException("解析结果错误 : " + valueStr);
//            }
            map.put(name, valueStr);
        }
        boolean signatureValid = ZFBSignUtil.rsaCheckV1(map);
        if(signatureValid) {
            String tradeStatus = map.get("trade_status");
            if("TRADE_SUCCESS".equals(tradeStatus)){
                // 订单号
                String outTradeNo = map.get("out_trade_no");
                // 支付宝订单号
                String zfbTradeNo = map.get("trade_no");
                // 订单金额
                String amountStr = map.get("total_amount");
                res = "success";
            }
        }
        response.getWriter().println(res);
    }

    /**
     * 腾讯云上传视频回调
     * @param mediaMap
     * @return
     */
    @PostMapping("/tx/receive")
    public ResponseEntity<Map<String,Integer>> receive(@RequestBody Map<String,Object> mediaMap){
        Map<String,Integer> responseMap = new HashMap<>(16);
        responseMap.put("code",0);
        String eventType = mediaMap.get("event_type").toString();
        //100表示该回调消息为录制文件生成的消息
        if(!"100".equals(eventType)){
            return new ResponseEntity<>(responseMap, HttpStatus.OK);
        }
        String timetableId = mediaMap.get("stream_id").toString();
//        if (timetableId.lastIndexOf(SDK_APP_ID) != -1) {
//            return new ResponseEntity<>(responseMap, HttpStatus.OK);
//        }
//        if (!timetableId.contains(SDK_APP_ID)) {
//            return new ResponseEntity<>(responseMap, HttpStatus.OK);
//        }
        String streamParam = mediaMap.get("stream_param").toString();
        String[] paramsArray = streamParam.split("&");
        Map<String, String> streamParamMap = new HashMap<>(paramsArray.length);
        for (String params : paramsArray) {
            String[] param = params.split("=");
            streamParamMap.put(param[0], param[1]);
        }
        String userIdBase64Str = streamParamMap.get("userid");
        String userId = Base64.decodeStr(userIdBase64Str,"UTF-8");
        String roomId = streamParamMap.get("roomid");
        String videoUrl = mediaMap.get("video_url").toString();
        //TODO 这里进行逻辑处理
        return new ResponseEntity<>(responseMap,HttpStatus.OK);
    }

}
